package com.ben.tcptester.tcpclient.netty;

import com.ben.tcptester.Entity.Client;
import com.ben.tcptester.Entity.Server;
import com.ben.tcptester.bean.ws.EventMessage;
import com.ben.tcptester.bean.ws.EventType;
import com.ben.tcptester.bean.ws.WsBaseResponse;
import com.ben.tcptester.bean.ws.WsMsgType;
import com.ben.tcptester.util.JsonUtil;
import com.ben.tcptester.web.websocket.MyTextWebSocketHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.TextMessage;

/**
 * Created by Peter on 2017/7/4.
 */
public class TcpTesterClient extends Thread {

    private static final Logger logger = LoggerFactory.getLogger(TcpTesterClient.class);

    private Server srv;

    public TcpTesterClient(Server srv) {
        this.srv = srv;
    }

    @Override
    public void run() {
        try {
            boolean isSuccess = connect(srv);//创建tpc客户端连接
            if (!isSuccess) {
                sendWsEvent(EventType.connectFail, srv);
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 通过WebSocket向界面推送连接失败的消息
            sendWsEvent(EventType.connectFail, srv);
        }
    }

    private void sendWsEvent(String event, Object key) {
        EventMessage eventMessage = new EventMessage(event, key);
        WsBaseResponse message = new WsBaseResponse(WsMsgType.event, eventMessage);
        TextMessage textMessage = new TextMessage(JsonUtil.toJson(message));
        MyTextWebSocketHandler.sendMessageToAllUser(textMessage);
    }

    // 每次连接都会向Server中添加一个Client对象
    public boolean connect(Server srv) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();

        boolean isConnectSuccess = false;
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class);
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    //日志
                    ch.pipeline().addLast("decoder", new StringDecoder());
                    ch.pipeline().addLast("encoder", new StringEncoder());
                    ch.pipeline().addLast("logging", new LoggingHandler(LogLevel.INFO));
                    ch.pipeline().addLast(new UserHandler());
                }
            });
            b.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(640, 10240, 655360));
            // 启动客户端
            ChannelFuture f = b.connect(srv.getHost(), srv.getPort()).sync();
            isConnectSuccess = f.isSuccess(); // (5)

            if (isConnectSuccess) {
                Client client = new Client(f.channel());
                srv.addClient(client); // 每次连接都会向Server中添加一个Client对象
                sendWsEvent(EventType.connectSuccess, srv);

                logger.info("connectSuccess success");
            } else {
                logger.info("connectSuccess failed");
            }

            //阻塞同步等待关闭连接（阻塞），不写此句代码连接会直接关闭，
            f.channel().closeFuture().sync();

        } catch (Exception e) {
            logger.info("connectSuccess failed  (Exception：" + e.getMessage() + ") ");
            throw e;
//            logger.error(e.getMessage(), e);
        } finally {
            group.shutdownGracefully();
            logger.info("TcpClient连接关闭，成功释放资源。");
        }

        return isConnectSuccess;
    }


}
